#
# Ronin Exploits - A Ruby library for Ronin that provides exploitation and
# payload crafting functionality.
#
# Copyright (c) 2007-2013 Hal Brodigan (postmodern.mod3 at gmail.com)
#
# This file is part of Ronin Exploits.
#
# Ronin is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ronin is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ronin.  If not, see <http://www.gnu.org/licenses/>
#

require 'ronin/model'
require 'ronin/os'

module Ronin
  module Model
    module TargetsOS
      #
      # Adds an `os` relation between a model and the `Ronin::OS` model.
      #
      def self.included(base)
        base.send :include, InstanceMethods
        base.send :extend, ClassMethods

        base.module_eval do
          # The targeted OS
          belongs_to :os,
                     model: 'Ronin::OS',
                     required: false
        end

        OS.has OS.n, base.relationship_name, model: base.name
      end

      module ClassMethods
        #
        # Queries all resources targeting a specific Operating System.
        #
        # @param [OS, Hash, Symbol, #to_s] os
        #   The Operating System to search for.
        #
        # @param [String] version
        #   Optional version of the Operating System.
        #
        # @return [DataMapper::Collection]
        #   The matching resources.
        #
        # @since 1.0.0
        #
        # @api public
        #
        def targeting_os(os,version=nil)
          conditions = case os
                       when OS, Hash
                         {os: os}
                       when Symbol
                         unless License.methods(false).include?(os)
                           raise(ArgumentError,"unknown OS: #{os}")
                         end

                         {os: OS.send(os)}
                       else
                         if version
                           {'os.name' => os.to_s, 'os.version' => version.to_s}
                         else
                           {'os.name' => os.to_s}
                         end
                       end

          all(conditions)
        end
      end

      module InstanceMethods
        #
        # Targets a Operating System.
        #
        # @param [String] name
        #   The name of the targeted Operating System.
        #
        # @param [String] version
        #   The version of the targeted Operating System.
        #
        # @return [OS]
        #   The targeted Operating System.
        #
        # @example
        #   t.targets_os 'FreeBSD', '7.1'
        #   # => #<Ronin::OS @id=nil @name="FreeBSD" @version="7.1">
        #
        # @since 1.0.0
        #
        def targets_os(name,version=nil)
          self.os = OS.first_or_new(name: name, version: version)
        end
      end
    end
  end
end
